package etxt2db.main;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ResultsStatistics {

	private static int tp;
	private static int fp;
	private static int fn;
	private static int total;

	/**
	 * @param args
	 * @throws FileNotFoundException 
	 */
	public static void main(String[] args) throws FileNotFoundException {

		int[] split = {1,2,3,4,5,6,7,8,9};
		
		String[] names = {"HMM","MEMM","CRF","SVM"};
		
		for (int i = 0; i < names.length; i++) {
			
			for (int spl = 0; spl < split.length; spl++) {
								
				String folder = "/home/pjbarrio/Dataset/NaturalDisaster/SimpleData/" + split[spl] + "/testingDirectory/";

				String idealResults = folder + "idealResults/";
				
				String results = folder + "results" + names[i] +"/";
								
				System.setOut(new PrintStream(new File(results + "output.statistics")));
				
				System.out.println("START");
				
				String tag = "NATURALDISASTER";
								
				File resultsFolder = new File(results);
				
				File[] files = resultsFolder.listFiles();
				
				for (File file : files) {
					
					if (!file.getName().endsWith(".txt"))
						continue;
					
					File idealFile = new File(idealResults + file.getName());
					
					List<String> extractedResults = getExtracted(file,tag);
			
					List<String> extractedIdealResults = getExtracted(idealFile,tag);
					
					System.out.println(file.getName());
					
					updateStats(extractedResults, extractedIdealResults);
					
				}
				System.out.println("True Positive: " + tp);
				System.out.println("False Positive: " + fp);
				System.out.println("False Negative: " + fn);
				System.out.println("PRECISION: " + ((double)tp/(double)(tp+fp)));
				System.out.println("RECALL: " + ((double)tp/(double)(tp + fn)));

				System.err.println(results + "output.statistics");
				System.err.println(names[i] + " - " + split[spl]);
			}
			
		}
		
		
	}

	private static void updateStats(List<String> extractedResults,
			List<String> extractedIdealResults) {
		
		Collections.sort(extractedResults);
		
		Collections.sort(extractedIdealResults);
		
		System.out.println("EXTRACTED: " + getString(0,extractedResults));
		
		System.out.println("IDEAL    : " + getString(0,extractedIdealResults));
		
		tp += calculateTruePositive(extractedResults,extractedIdealResults);
		
		fp += calculateFalsePositive(extractedResults,extractedIdealResults);
		
		fn += calculateFalseNegative(extractedResults,extractedIdealResults);
		
		total += extractedIdealResults.size();
		
		System.err.println(tp + " - " + fp + " - " + fn + " - " + total);
			
		
	}

	private static String getString(int start,List<String> objects) {
		
		String ret = "";
		
		for (int i = start; i < objects.size(); i++) {
			
			ret = ret + " - " + objects.get(i);
			
		}
		
		return ret;
	}

	private static int calculateFalseNegative(List<String> extractedResults,
			List<String> extractedIdealResults) {
		
		int extractedI = 0;
		
		int falseNegative = 0;
				
		for (int i = 0; i < extractedIdealResults.size(); i++) {

			if (extractedI == extractedResults.size()){
				
				falseNegative += (extractedIdealResults.size() - i);
				
				System.err.println("FALSE NEGATIVE: " + getString(i, extractedIdealResults) + " - " + falseNegative);
				
				break;
			}
			
			if (extractedIdealResults.get(i).equals(extractedResults.get(extractedI))){
				
				//SAME STRING
				extractedI++;
				continue;
			
			}
			
			if (extractedIdealResults.get(i).compareTo(extractedResults.get(extractedI)) < 0){

				//IDEAL LESS THAN EXTRACTED. FALSE NEGATIVE!
				
				falseNegative++;
				
				System.err.println("FALSE NEGATIVE: " + extractedIdealResults.get(i) + " - " + falseNegative);
				
				continue;
			}
			
			if (extractedIdealResults.get(i).compareTo(extractedResults.get(extractedI)) > 0){
				
				extractedI++;
				i--;
				continue;
			}
			
		}
		
		return falseNegative;
		
	}

	private static int calculateFalsePositive(List<String> extractedResults,
			List<String> extractedIdealResults) {
		
		int idealI = 0;
		
		int falsePositive = 0;
								
		for (int i = 0; i < extractedResults.size(); i++) {

			if (idealI == extractedIdealResults.size()){
				
				falsePositive+= (extractedResults.size() - i);
				
				System.err.println("FALSE POSITIVE: " + getString(i, extractedResults) + " - " + falsePositive);
				
				break;
			}
			
			if (extractedIdealResults.get(idealI).equals(extractedResults.get(i))){
				
				//SAME STRING
				
				idealI++;
				continue;
			}
			
			if (extractedIdealResults.get(idealI).compareTo(extractedResults.get(i)) < 0){

				//IDEAL LESS THAN EXTRACTED. WE DON'T KNOW YET IF IT'S FALSE
				
				idealI++;
				i--;				
				continue;
			}
			
			if (extractedIdealResults.get(idealI).compareTo(extractedResults.get(i)) > 0){

				//IDEAL WENT OVER EXTRACTED WITH NO MATCHING. FALSE POSITIVE.
				
				falsePositive++;				
				
				System.err.println("FALSE POSITIVE: " + extractedResults.get(i) + " - " + falsePositive);
				continue;
			}
			
		}
		
		return falsePositive;
	}

	private static int calculateTruePositive(List<String> extractedResults,
			List<String> extractedIdealResults) {
		
		int idealI = 0;
		
		int truePositive = 0;
								
		for (int i = 0; i < extractedResults.size(); i++) {

			if (idealI == extractedIdealResults.size()){
				break;
			}
			
			if (extractedIdealResults.get(idealI).equals(extractedResults.get(i))){
				
				//SAME. TRUE POSITIVE.
				
				idealI++;
				truePositive++;
				continue;
			}
			
			if (extractedIdealResults.get(idealI).compareTo(extractedResults.get(i)) < 0){

				//IDEAL LESS THAN EXTRACTED. KEEP LOOKING.
				
				idealI++;
				i--;				
				continue;
			}
			
		}
		
		return truePositive;
		
	}

	private static List<String> getExtracted(File file,String tag) {
		
		ArrayList<String> ret = new ArrayList<String>();
		
		String patter = "<" + tag + ">(.*?)</" + tag + ">";
		
		Pattern pattern = Pattern.compile(patter);
		
		String text = loadFileasString(file);
		
		Matcher matcher = pattern.matcher(text);
		
		while (matcher.find()){
			
			for (int i=1;i<=matcher.groupCount();i++){
				
				ret.add(matcher.group(i));
				
			}
			
		}
		
		return ret;
	}

	private static String loadFileasString(File file) {
		
		byte[] buffer = new byte[(int) file.length()];
	    BufferedInputStream f = null;
	    try {
	        f = new BufferedInputStream(new FileInputStream(file.getAbsolutePath()));
	        f.read(buffer);
	    } catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
	        if (f != null) try { f.close(); } catch (IOException ignored) { }
	    }
	    return new String(buffer);
		
	}

}
